Why in JavaScript both "Object instanceof Function" and "Function instanceof Object" return true?
一、ECMA5.1规范中instanceof
/*
how instanceof is defined by ECMA 5.1 Specification:
The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated as follows:
Let lref be the result of evaluating RelationalExpression.
Let lval be GetValue(lref).
Let rref be the result of evaluating ShiftExpression.
Let rval be GetValue(rref).
If Type(rval) is not Object, throw a TypeError exception.
If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
Return the result of calling the [[HasInstance]] internal method of rval with argument lval.
------->Not all objects will have [[HasInstance]] internal method, but functions.
console.log(Object instanceof {});
TypeError: Expecting a function in instanceof check, but got <Object>
*/
二、ECMA5.1规范中[[HasInstance]]
/*
how [[HasInstance]] has been defined in the ECMA 5.1 specification:
Assume F is a Function object.
When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:
If V is not an object, return false.
Let O be the result of calling the [[Get]] internal method of F with property name "prototype".
If Type(O) is not Object, throw a TypeError exception.
Repeat
Let V be the value of the [[Prototype]] internal property of V.
If V is null, return false.
If O and V refer to the same object, return true.
------->Take the prototype property of F and compare it
with the [[Prototype]] internal property of O until it becomes null or prototype of F is the same as O.
*/
三、ECMA5.1规范中[[prototype]]
/*
what is the [[prototype]] internal property:
All objects have an internal property called [[Prototype]].
The value of this property is either null or an object and is used for implementing inheritance.
Whether or not a native object can have a host object as its [[Prototype]] depends on the implementation.
Every [[Prototype]] chain must have finite length(that is, starting from any object,
recursively accessing the [[Prototype]] internal property must eventually lead to a null value).
------->We can get this internal property with the Object.getPrototypeOf function
*/
/*
[[HasInstance]] also talks about another property called prototype, which is specific to the Function objects.
The value of the prototype property is used to
initialise the [[Prototype]] internal property of a newly created object
before the Function object is invoked as a constructor for that newly created object.
------->when a function object is used as a constructor, a new object will be created
and the new object will have its internal [[Prototype]] initialized with this prototype property
------->function Test() {}
Test.prototype.print = console.log;
console.log(Object.getPrototypeOf(new Test()) === Test.prototype);
# true
*/
console.log("-------------------------------------------------------" + "\n\n");
四、分析过程
//分析:
console.log(Object instanceof Function);
// true
// It will fetch Function.prototype first and it will try
// and find if that object is in the prototype hierarchy of Object. Let us see how that turns out
console.log(Function.prototype);
// [Function: Empty]
console.log(Object.getPrototypeOf(Object));
// [Function: Empty]
console.log(Object.getPrototypeOf(Object) === Function.prototype);
// true
//Since the Function.prototype matches the Object's internal property [[Prototype]], it returns true
console.log(Function instanceof Object);
// true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype
// true
//Here, first we get the Object.prototype, which is {}.
// Now it is trying to find if the same object {} is there in the Function's prototype chain.
// Immediate parent of Function is and Empty function.
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
//It is not the same as Object.prototype
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
//But the [[HasInstance]] algorithm doesn't stop there. It repeats and gets up one more level
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
//And this is the same as Object.prototype. That is why this returns true.
console.log("-------------------------------------------------------" + "\n\n");
五、证明流程
console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
//{}
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype);
// true
console.log(Object.getPrototypeOf(Function));
//[Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
console.log("-------------------------------------------------------" + "\n\n");
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。